#include "../../include/utils/DbPool/DbConnection.hpp"
#include <muduo/base/Logging.h>

using namespace http::db;

DbConnection::DbConnection(const std::string &host, const std::string &user, const std::string &password, const std::string &database)
    : _host(host), _user(user), _password(password), _database(database)
{
    try
    {
        // 获取数据库连接
        sql::mysql::MySQL_Driver *driver = sql::mysql::get_mysql_driver_instance();
        _connection.reset(driver->connect(_host, _user, _password));
        if (_connection)
        {
            // 设置数据库
            _connection->setSchema(_database);
            // 设置连接属性
            _connection->setClientOption("OPT_RECONNECT", "true");     // 设置自动重连
            _connection->setClientOption("OPT_CONNECT_TIMEOUT", "10"); // 设置连接超时时间
            _connection->setClientOption("multi_statements", "false"); // 设置是否支持多语句执行

            std::unique_ptr<sql::Statement> stmt(_connection->createStatement());
            if (stmt)
            {
                // 设置字符集
                stmt->execute("SET NAMES utf8");
                LOG_INFO << "Database connection successful";
            }
        }
    }
    catch (sql::SQLException &e)
    {
        LOG_ERROR << "Database connection failed: " << e.what();
        throw DbException(e.what()); // 将底层技术异常转换为业务异常 业务层不需要知道底层用的是mysql还是其他数据库
    }
}

DbConnection::~DbConnection()
{
    try
    {
        cleanUp();
    }
    catch (...)
    {
        // 忽略异常
    }
    LOG_INFO << "Database connection closed";
}

bool DbConnection::isValid()
{
    try
    {
        if (!_connection)
            return false;
        std::unique_ptr<sql::Statement> stmt(_connection->createStatement());
        if (stmt)
        {
            stmt->execute("SELECT 1"); // 执行一个简单的查询 如果连接有效 会返回一个结果集 否则会抛出异常
            return true;
        }
        return false;
    }
    catch (const sql::SQLException &e)
    {
        LOG_ERROR << "Database connection check failed: " << e.what();
        return false;
    }
}

void DbConnection::reconnect()
{
    try
    {
        if (_connection)
        {
            _connection->reconnect();
            LOG_INFO << "Database connection reconnected";
        }
        else
        {
            sql::mysql::MySQL_Driver *driver = sql::mysql::get_mysql_driver_instance();
            _connection.reset(driver->connect(_host, _user, _password));
            _connection->setSchema(_database);
        }
    }
    catch (const sql::SQLException &e)
    {
        LOG_ERROR << "Database connection reconnect failed: " << e.what();
        throw DbException(e.what());
    }
}

void DbConnection::cleanUp()
{
    // 加锁 防止多个线程同时访问 一个在执行sql查询 这里又要cleanUp清理连接
    std::lock_guard<std::mutex> lock(_mutex);
    try
    {
        if (_connection)
        {
            // 确保所有事务都已完成
            if (!_connection->getAutoCommit())
            {
                _connection->rollback();
                _connection->setAutoCommit(true);
            }

            // 清理所有未处理的结果集
            std::unique_ptr<sql::Statement> stmt(_connection->createStatement());
            while (stmt->getMoreResults())
            {
                auto res = stmt->getResultSet();
                while (res && res->next())
                {
                    // 释放结果集
                }
            }
        }
    }
    catch (const std::exception &e)
    {
        LOG_WARN << "Database connection cleanup failed: " << e.what();
        try
        {
            reconnect();
        }
        catch (...)
        {
            // 忽略异常
        }
    }
}

bool DbConnection::ping()
{
    // 执行简单查询检查连接
    try
    {
        std::unique_ptr<sql::Statement> stmt(_connection->createStatement()); // 创建一个语句对象
        std::unique_ptr<sql::ResultSet> res(stmt->executeQuery("SELECT 1"));  // 执行一个简单的查询 如果连接有效 会返回一个结果集 否则会抛出异常
        return true;
    }
    catch (const sql::SQLException &e)
    {
        LOG_ERROR << "Database connection ping failed: " << e.what();
        return false;
    }
}

template <typename... Args>
sql::ResultSet *DbConnection::executeQuery(const std::string &sql, Args... args)
{
    std::lock_guard<std::mutex> lock(_mutex);
    try
    {
        // 直接创建新的预处理语句，不使用缓存
        std::unique_ptr<sql::PreparedStatement> pstmt(_connection->prepareStatement(sql));
        bindParams(pstmt.get(), 1, std::forward<Args>(args)...); // 绑定参数 forward 完美转发
        return pstmt->executeQuery();
    }
    catch (const sql::SQLException &e)
    {
        LOG_ERROR << "Database connection query failed: " << e.what() << " sql: " << sql;
        throw DbException(e.what());
    }
}

template <typename... Args>
int DbConnection::executeUpdate(const std::string &sql, Args... args)
{
    std::lock_guard<std::mutex> lock(_mutex);
    try
    {
        // 直接创建新的预处理语句，不使用缓存
        std::unique_ptr<sql::PreparedStatement> pstmt(_connection->prepareStatement(sql));
        bindParams(pstmt.get(), 1, std::forward<Args>(args)...); // 绑定参数 forward 完美转发
        return pstmt->executeUpdate();
    }
    catch (const sql::SQLException &e)
    {
        LOG_ERROR << "Database connection update failed: " << e.what() << " sql: " << sql;
        throw DbException(e.what());
    }
}
